package com.winning.pmph.ctrl;

import com.google.common.collect.Maps;
import com.winning.pmph.entity.Task;
import com.winning.pmph.service.TaskService;
import com.winning.pmph.utils.ApplicationContextUtil;
import com.winning.pmph.utils.FilePath;
import com.winning.pmph.utils.UploadFileUtil;
import com.winning.pmph.utils.ZipUtil;
import com.winning.pmph.vo.FileVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;
import java.util.Map;

@Api(value = "文件上传接口")
@RestController
@RequestMapping("/pmph/action/file")
@Slf4j
public class FileCtrl {

    @Resource
    private TaskService taskService;
    @Resource
    private FilePath filePath;

    @ApiOperation(value = "upload", notes = "上传文件接口")
    @PostMapping("upload")
    public Map<String, String> upload(MultipartFile file, @RequestParam String uploadPath) {
        Map<String, String> map = Maps.newHashMap();
        log.debug("上传文件");
        String path = ApplicationContextUtil.BASE_DOWN_FORDER + uploadPath;
        log.debug("上传路径：" + path);
        String originName = UploadFileUtil.uploadFile(file, path, false);
        map.put("storedPath", filePath.getFilePath() + uploadPath + "/" + originName);
        map.put("originName", originName);
        return map;
    }

    @ApiOperation(value = "uploadImg", notes = "上传图片接口")
    @PostMapping("uploadImg")
    public FileVo uploadImg(MultipartFile file, @RequestParam String uploadPath) {
        if (org.apache.commons.lang3.StringUtils.isEmpty(uploadPath)) {
            throw new RuntimeException("存储路径为空");
        }
        log.debug("上传图片");
        String path = ApplicationContextUtil.BASE_DOWN_FORDER + uploadPath;
        log.debug("上传路径：" + path);
        String storedName = UploadFileUtil.uploadFile(file, path, true);
        return new FileVo(filePath.getImgPath() + uploadPath + "/" + storedName);
    }

    @ApiOperation(value = "getFile", notes = "获取文件接口")
    @GetMapping("getFile")
    public void getFile(HttpServletRequest request, HttpServletResponse response, String filename) throws IOException {
        String originName = StringUtils.substringAfterLast(filename, "/");
        // 设置文件MIME类型
        response.setContentType(request.getServletContext().getMimeType(filename));
        // 设置Content-Disposition
        String headerInfo = "attachment;filename=" + java.net.URLEncoder.encode(originName, "UTF-8");
        String agentName = request.getHeader("USER-AGENT");
        if (StringUtils.isNotBlank(agentName) && agentName.toLowerCase().indexOf("firefox") > 0) {
            headerInfo = "attachment;filename*=utf-8'zh_cn'" + java.net.URLEncoder.encode(filename, "UTF-8");
        }
        response.setHeader("Content-Disposition", headerInfo);
        // 获取目标文件的绝对路径
        String fullFileName = ApplicationContextUtil.BASE_DOWN_FORDER + filename;
        File file = new File(fullFileName);
        int fSize = Integer.parseInt(String.valueOf(file.length()));
        response.setHeader("Accept-Ranges", "bytes");
        response.setHeader("Content-Length", String.valueOf(fSize));
        FileUtils.copyFile(file, response.getOutputStream());
    }

    @ApiOperation(value = "uploadFile", notes = "获取压缩包接口")
    @GetMapping("uploadFile")
    public void uploadFile(String taskId, HttpServletResponse response) {
        Task task = taskService.getById(taskId);
        String filePath = ApplicationContextUtil.BASE_DOWN_FORDER + "/file/task/" + taskId;
        // 设置压缩文件参数
        ZipParameters parameters = new ZipParameters();
        // 设置压缩方法
        parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
        // 设置压缩级别
        parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
        ZipFile zipFile;
        File zipTempFile = new File(ApplicationContextUtil.BASE_DOWN_FORDER + task.getName() + ".zip");
        OutputStream ous = null;
        InputStream fis = null;
        try {
            zipFile = new ZipFile(zipTempFile);
            File srcFile = new File(filePath);
            //开始压缩
            File[] files = srcFile.listFiles();
            if (files == null) {
                return;
            }
            for (File item : files) {
                zipFile.addFile(item, parameters);
            }
            File file = new File(ApplicationContextUtil.BASE_DOWN_FORDER + task.getName() + ".zip");
            fis = new BufferedInputStream(new FileInputStream(file));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            response.reset();
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(task.getName(), "UTF-8"));
            response.addHeader("Content-Length", "" + file.length());

            ous = new BufferedOutputStream(response.getOutputStream());
            ous.write(buffer);
        } catch (Exception e) {
            throw new RuntimeException("压缩文件时异常");
        } finally {
            ZipUtil.deleteDir(ApplicationContextUtil.BASE_DOWN_FORDER + task.getName() + ".zip");
            if (ous != null) {
                try {
                    ous.flush();
                    ous.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
